package org.example.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.example.domain.ResponseResult;
import org.example.domain.dto.MenuLIstDto;
import org.example.domain.entity.Menu;
import org.example.enums.AppHttpCodeEnum;
import org.example.exception.SystemException;
import org.example.mapper.MenuMapper;
import org.example.service.MenuService;
import org.example.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper,Menu> implements MenuService {

    private final MenuMapper menuMapper;

    @Override
    public List<String> selectPermsByUserId(Integer userId){
        if(userId == 1){
            List<Menu> menuList = menuMapper.selectPermsByAdmin();
            List<String> perms = menuList.stream().map(new Function<Menu, String>() {

                @Override
                public String apply(Menu menu) {
                    return menu.getPerms();
                }
            }).collect(Collectors.toList());

            return perms;
        }
        return menuMapper.selectPermsByUserId(userId);
    }

    @Override
    public List<Menu> selectRouterMenuTreeByUserId(Integer userId) {
        List<Menu> menus = null;
        if(SecurityUtils.isAdmin()){
            menus = menuMapper.selectAllRouterMenu();
        }else{
            menus = menuMapper.selectRouterMenuTreeByUserId(userId);
        }
        List<Menu> menuList = new ArrayList<>();
        for(Menu menu:menus){
            if(menu.getParentId() == 0){
                menuList.add(dfs(menu,menu.getId(),menus));
            }
        }
        return menuList;
    }

    @Override
    public ResponseResult menuTree() {
        List<Menu> menuList = new ArrayList<>();
        List<Menu> menus = menuMapper.selectAllMenu();
        for(Menu menu:menus){
            if(menu.getParentId() == 0){
                menuList.add(dfs(menu,menu.getId(),menus));
            }
        }
        return ResponseResult.okResult(menuList);
    }

    @Override
    public List<Menu> selectMenuByRoleId(Integer id) {
        return menuMapper.selectMenuByRoleId(id);
    }

    @Override
    public ResponseResult getMenuLIst(MenuLIstDto menuLIstDto) {

        List<Menu> menus = menuMapper.getMenuList(menuLIstDto);
        List<Menu> menuList = new ArrayList<>();
        int[] vis = new int[1024];
        for(Menu menu : menus){
            if(vis[menu.getId()] == 0){
                vis[menu.getId()]++;
                dfs2(menu,menu.getId(),menus,vis);
            }
        }
        for(Menu menu : menus){
            if(vis[menu.getId()] == 1){
                menuList.add(menu);
            }
        }
        return ResponseResult.okResult(menuList);
    }

    @Override
    public List<Menu> treeList() {
        List<Menu> menuList = new ArrayList<>();
        List<Menu> menus = menuMapper.selectAllMenu();
        for(Menu menu:menus){
            if(menu.getParentId() == 0){
                menuList.add(dfs(menu,menu.getId(),menus));
            }
        }
        return menuList;
    }

    @Override
    public ResponseResult addMenu(Menu menu) {
        List<Menu> menus = new ArrayList<>();

        if(!"F".equals(menu.getMenuType())){
            menus = menuMapper.selectByPath(menu.getPath());
        }

        if(!CollectionUtils.isEmpty(menus)){
            throw new SystemException(AppHttpCodeEnum.MENU_PATH_EXIST);
        }
        return ResponseResult.okResult(save(menu));
    }

    @Override
    public ResponseResult updateMenu(Menu menu) {
        List<Menu> menus = new ArrayList<>();
        if(!"F".equals(menu.getMenuType())){
            menus = menuMapper.selectByPath(menu.getPath());
        }

        if(menus.size()>=2){
            throw new SystemException(AppHttpCodeEnum.MENU_PATH_EXIST);
        }
        return ResponseResult.okResult(updateById(menu));
    }


    private Menu dfs(Menu menu,Integer id,List<Menu> menus){
        menu.setChildren(new ArrayList<>());
        for(int i=0;i<menus.size();i++){
            if(menus.get(i).getParentId() == 0 ){
                continue;
            }
            if(menus.get(i).getParentId() == id){
                dfs(menus.get(i),menus.get(i).getId(),menus);
                menu.getChildren().add(menus.get(i));
            }
        }
        return menu;
    }


    private Menu dfs2(Menu menu,Integer id,List<Menu> menus,int[] vis){
        menu.setChildren(new ArrayList<>());
        for(int i=0;i<menus.size();i++){
            if(menus.get(i).getParentId() != id){
                continue;
            }
            else{
                if(vis[menus.get(i).getId()] == 0 ){
                    vis[menus.get(i).getId()] = vis[id] + 1;
                    dfs2(menus.get(i),menus.get(i).getId(),menus,vis);
                    menu.getChildren().add(menus.get(i));
                }
                else{
                    menu.getChildren().add(menus.get(i));
                    vis[menus.get(i).getId()] = vis[id] + 1;
                }
            }
        }
        return menu;
    }

}
